﻿using BLevy.Datos.Interfases;
using BLevy.Entidad;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;

namespace BLevy.Datos.Repositories
{
    public interface ICobradorLiquidacionRepository : IRepository<CobradorLiquidacion>
    {
        int AddDetalleLiquidacion(CobradorLiquidacionDetalle detalle);
        int RegistrarPagoLiquidacion(int cobradorcobro_id);
        IList<CobradorLiquidacionDetalle> FindAllDetallesConCobradorFiltro(string numero_cupon, int? cobrador_id, DateTime? desde, DateTime? hasta);
        IList<CobradorLiquidacionDetalle> FindByIdLiquidacion(int id);
        IList<CobradorLiquidacion> FindAllConCobrador();
        IList<CobradorLiquidacion> FindAllConCobradorFiltro(int? cobrador_id, DateTime? desde, DateTime? hasta);
        IList<CobradorLiquidacionDetalle> FindLiquidacionDetallesPorLiquidacionId(int liquidacion_id);
        int CobradorLiquidacionPagoRegistrar(CobradorLiquidacionPago liquidacionpago);
        int CobradorLiquidacionCambiarEstado(int liquidacion_id);
    }

    public class CobradorLiquidacionRepository : ICobradorLiquidacionRepository
    {

        protected readonly IDbConnection _db;

        public CobradorLiquidacionRepository()
        {
            try
            {
                _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString());
            }
            catch(Exception e)
            { 
                throw e; 
            }
        }


        public IList<CobradorLiquidacion> FindAll()
        {
            throw new NotImplementedException();
        }

        public IQueryable<CobradorLiquidacion> Find(System.Linq.Expressions.Expression<Func<CobradorLiquidacion, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public CobradorLiquidacion FindById(int id)
        {
            string query = "SELECT * FROM COBRADORESLIQUIDACIONES " +
                "WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CobradorLiquidacion>(query, new
                    {
                        id = id
                    }).SingleOrDefault();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public int Add(CobradorLiquidacion newEntity)
        {
            const string query = "INSERT INTO COBRADORESLIQUIDACIONES (FECHA_LIQUIDACION, COBRADOR_ID, TOTAL, ESTADO) " +
                "VALUES (@fecha_liquidacion, @cobrador_id, @total, @estado);" +
                "SELECT LAST_INSERT_ID();";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<int>(query, new
                    {
                        fecha_liquidacion = newEntity.fecha_liquidacion,
                        cobrador_id = newEntity.cobrador_id,
                        total = newEntity.total,
                        estado = newEntity.estado
                    }).Single();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Remove(int id)
        {
            throw new NotImplementedException();
        }

        public int Modify(CobradorLiquidacion entity)
        {
            throw new NotImplementedException();
        }

        public int AddDetalleLiquidacion(CobradorLiquidacionDetalle detalle)
        {
            const string query = "INSERT INTO COBRADORESLIQUIDACIONESDETALLE (COBRADORLIQUIDACION_ID, COBRADORCOBRO_ID, COMISION) " + 
                "VALUES (@cobradorliquidacion_id, @cobradorcobro_id, @comision)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        cobradorliquidacion_id = detalle.cobradorliquidacion_id,
                        cobradorcobro_id = detalle.cobradorcobro_id,
                        comision = detalle.comision
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int RegistrarPagoLiquidacion(int cobradorcobro_id)
        {
            const string query = "UPDATE COBRADORESCOBROS SET ESTADO = @estado " +
                "WHERE ID = @cobradorcobro_id";
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { estado = "P", cobradorcobro_id = cobradorcobro_id });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<CobradorLiquidacionDetalle> FindAllDetallesConCobradorFiltro(string numero_cupon, int? cobrador_id, DateTime? desde, DateTime? hasta)
        {
            const string query = "SELECT * FROM COBRADORESLIQUIDACIONESDETALLE " +
                "INNER JOIN COBRADORESLIQUIDACIONES ON COBRADORESLIQUIDACIONES.ID = COBRADORESLIQUIDACIONESDETALLE.COBRADORLIQUIDACION_ID " +
                "INNER JOIN COBRADORES ON COBRADORES.ID = COBRADORESLIQUIDACIONES.COBRADOR_ID " +
                "INNER JOIN COBRADORESCOBROS ON COBRADORESCOBROS.ID = COBRADORESLIQUIDACIONESDETALLE.COBRADORCOBRO_ID " +
                "INNER JOIN COBROS ON COBROS.ID = COBRADORESCOBROS.COBRO_ID " +
                "INNER JOIN CUPONES ON CUPONES.ID = COBROS.CUPON_ID " +
                "WHERE ((CUPONES.NUMERO = @numero_cupon) OR (@numero_cupon IS NULL)) " +
                "AND ((COBRADORES.ID = @cobrador_id) OR (@cobrador_id IS NULL)) ";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CobradorLiquidacionDetalle, CobradorLiquidacion, Cobrador, CobradorCobro, Cobro, Cupon, CobradorLiquidacionDetalle>(query,
                        (detalle, liquidacion, cobrador, cobrador_cobro, cobro, cupon) =>
                        {
                            detalle.cobrador_liquidacion = liquidacion;
                            detalle.cobrador_liquidacion.cobrador = cobrador;
                            detalle.cobrador_cobro = cobrador_cobro;
                            detalle.cobrador_cobro.cobro = cobro;
                            detalle.cobrador_cobro.cobro.cupon = cupon;
                            return detalle;
                        }, new
                        {
                            numero_cupon = numero_cupon,
                            cobrador_id = cobrador_id
                        }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public IList<CobradorLiquidacionDetalle> FindByIdLiquidacion(int id)
        {
            const string query = "SELECT * FROM COBRADORESLIQUIDACIONESDETALLE " +
                "INNER JOIN COBRADORESLIQUIDACIONES ON COBRADORESLIQUIDACIONES.ID = COBRADORESLIQUIDACIONESDETALLE.COBRADORLIQUIDACION_ID " +
                "INNER JOIN COBRADORES ON COBRADORES.ID = COBRADORESLIQUIDACIONES.COBRADOR_ID " +
                "INNER JOIN COBRADORESCOBROS ON COBRADORESCOBROS.ID = COBRADORESLIQUIDACIONESDETALLE.COBRADORCOBRO_ID " +
                "INNER JOIN COBROS ON COBROS.ID = COBRADORESCOBROS.COBRO_ID " +
                "INNER JOIN CUPONES ON CUPONES.ID = COBROS.CUPON_ID " +
                "WHERE COBRADORESLIQUIDACIONES.ID = @id ";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CobradorLiquidacionDetalle, CobradorLiquidacion, Cobrador, CobradorCobro, Cobro, Cupon, CobradorLiquidacionDetalle>(query,
                        (detalle, liquidacion, cobrador, cobrador_cobro, cobro, cupon) =>
                        {
                            detalle.cobrador_liquidacion = liquidacion;
                            detalle.cobrador_liquidacion.cobrador = cobrador;
                            detalle.cobrador_cobro = cobrador_cobro;
                            detalle.cobrador_cobro.cobro = cobro;
                            detalle.cobrador_cobro.cobro.cupon = cupon;
                            return detalle;
                        }, new
                        {
                            id = id
                        }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<CobradorLiquidacion> FindAllConCobrador()
        {
            const string query = "SELECT * FROM COBRADORESLIQUIDACIONES " +
                "INNER JOIN COBRADORES ON COBRADORES.ID = COBRADORESLIQUIDACIONES.COBRADOR_ID";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CobradorLiquidacion, Cobrador, CobradorLiquidacion>(query,
                        (liquidacion, cobrador) =>
                        {
                            liquidacion.cobrador = cobrador;
                            return liquidacion;
                        }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public IList<CobradorLiquidacion> FindAllConCobradorFiltro(int? cobrador_id, DateTime? desde, DateTime? hasta)
        {
            const string query = "SELECT * FROM COBRADORESLIQUIDACIONES " +
                "INNER JOIN COBRADORES ON COBRADORES.ID = COBRADORESLIQUIDACIONES.COBRADOR_ID " +
                "WHERE ((COBRADORESLIQUIDACIONES.COBRADOR_ID = @cobrador_id) OR (@cobrador_id IS NULL)) " +
                "AND ((COBRADORESLIQUIDACIONES.FECHA_LIQUIDACION BETWEEN @desde AND @hasta) OR ((@desde IS NULL) OR (@hasta IS NULL)))";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CobradorLiquidacion, Cobrador, CobradorLiquidacion>(query,
                        (liquidacion, cobrador) =>
                        {
                            liquidacion.cobrador = cobrador;
                            return liquidacion;
                        }, new
                        {
                            cobrador_id = cobrador_id,
                            desde = desde,
                            hasta = hasta
                        }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public IList<CobradorLiquidacionDetalle> FindLiquidacionDetallesPorLiquidacionId(int liquidacion_id)
        {
            const string query = "SELECT * FROM COBRADORESLIQUIDACIONESDETALLE " +
                "INNER JOIN COBRADORESCOBROS ON COBRADORESCOBROS.ID = COBRADORESLIQUIDACIONESDETALLE.COBRADORCOBRO_ID " +
                "INNER JOIN COBROS ON COBROS.ID = COBRADORESCOBROS.COBRO_ID " + 
                "INNER JOIN CUPONES ON CUPONES.ID = COBROS.CUPON_ID " +
                "WHERE  COBRADORESLIQUIDACIONESDETALLE.COBRADORLIQUIDACION_ID = @liquidacion_id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<CobradorLiquidacionDetalle, CobradorCobro, Cobro, Cupon, CobradorLiquidacionDetalle>(query,
                        (detalle, cobrador_cobro, cobro, cupon) =>
                        {
                            detalle.cobrador_cobro = cobrador_cobro;
                            detalle.cobrador_cobro.cobro = cobro;
                            detalle.cobrador_cobro.cobro.cupon = cupon;
                            return detalle;
                        }, new { liquidacion_id = liquidacion_id}, splitOn:"id").ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public int CobradorLiquidacionPagoRegistrar(CobradorLiquidacionPago liquidacionpago)
        {
            string query = "INSERT INTO COBRADORESLIQUIDACIONESPAGOS (COBRADORLIQUIDACION_ID, FECHA, OBSERVACIONES) " +
                        "VALUES (@cobradorliquidacion_id, @fecha, @observaciones)";
            
            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new 
                    { 
                        cobradorliquidacion_id = liquidacionpago.cobradorliquidacion_id,
                        fecha = liquidacionpago.fecha,
                        observaciones = liquidacionpago.observaciones
                    });
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public int CobradorLiquidacionCambiarEstado(int liquidacion_id)
        {
            string query = "UPDATE COBRADORESLIQUIDACIONES SET ESTADO = 'P' " +
                "WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        id = liquidacion_id
                    });
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }
}
